package io.github.maojian.queue;

/**
 * 641. 设计循环双端队列
 * 设计实现双端队列。
 *
 * 实现 MyCircularDeque 类:
 *
 * MyCircularDeque(int k) ：构造函数,双端队列最大为 k 。
 * boolean insertFront()：将一个元素添加到双端队列头部。 如果操作成功返回 true ，否则返回 false 。
 * boolean insertLast() ：将一个元素添加到双端队列尾部。如果操作成功返回 true ，否则返回 false 。
 * boolean deleteFront() ：从双端队列头部删除一个元素。 如果操作成功返回 true ，否则返回 false 。
 * boolean deleteLast() ：从双端队列尾部删除一个元素。如果操作成功返回 true ，否则返回 false 。
 * int getFront() )：从双端队列头部获得一个元素。如果双端队列为空，返回 -1 。
 * int getRear() ：获得双端队列的最后一个元素。 如果双端队列为空，返回 -1 。
 * boolean isEmpty() ：若双端队列为空，则返回 true ，否则返回 false  。
 * boolean isFull() ：若双端队列满了，则返回 true ，否则返回 false 。
 *  
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/design-circular-deque
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 *
 */
public class Q641 {

    private int MAX_SIZE;

    private int size;

    private Node front;

    private Node last;

    public Q641(int k) {
        MAX_SIZE = k;
    }

    public boolean insertFront(int value) {
        if (isFull()) return false;
        Node node = new Node(value);
        if (isEmpty()) {
            node.next = node;
            node.pre = node;
            front = node;
            last = node;
        } else {
            node.next = front;
            node.pre = last;
            last.next = node;
            front.pre = node;
            front = node;
        }
        size++;
        return true;
    }

    public boolean insertLast(int value) {
        if (isFull()) return false;
        Node node = new Node(value);
        if (isEmpty()) {
            node.next = node;
            node.pre = node;
            front = node;
            last = node;
        } else {
            node.pre = last;
            node.next = front;
            last.next = node;
            front.pre = node;
            last = node;
        }
        size++;
        return true;
    }

    public boolean deleteFront() {
        if (isEmpty()) return false;
        if (size == 1) {
            size--;
            return true;
        }
        front = front.next;
        last.next = front;
        front.pre = last;
        size--;
        return true;
    }

    public boolean deleteLast() {
        if (isEmpty()) return false;
        if (size == 1) {
            size--;
            return true;
        }
        last = last.pre;
        last.next = front;
        front.pre = last;
        size--;
        return true;
    }

    public int getFront() {
        if(isEmpty()) return -1;
        return front.val;
    }

    public int getRear() {
        if(isEmpty()) return -1;
        return last.val;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public boolean isFull() {
        return size == MAX_SIZE;
    }

    class Node {
        int val;

        Node next;

        Node pre;

        public Node(int val) {
            this.val = val;
        }
    }
}
